#include <QLabel>
#include <QUrl>
#include <QDesktopServices>
#include <QFileInfo>
#include <QMessageBox>
#include <QMenu>
#include <QProcess>


#include <QToolTip>
#include <QDir>
#include <QPluginLoader>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutdialog.h"
#include "aboutabhidhaana.h"


#include "transliterator.h"
#include "minitranslator.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    filterAction = NULL;

    dictCombo = new QComboBox(ui->toolBar);

    inputEdit = new QLineEdit(ui->toolBar);
    inputEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));

    queryBtn = new QPushButton(tr("search"), inputEdit);
    queryBtn->setObjectName("queryButton");
    queryBtn->setIcon(QIcon(":/resources/pics/query.png"));
    queryBtn->setFlat(true);
    queryBtn->setFocusPolicy(Qt::NoFocus);
    queryBtn->setCursor(QCursor(Qt::PointingHandCursor));

    QHBoxLayout *buttonLayout = new QHBoxLayout();
    buttonLayout->setContentsMargins(0, 0, 0, 0);
    buttonLayout->addStretch();
    buttonLayout->addWidget(queryBtn);

    inputEdit->setLayout(buttonLayout);
    inputEdit->setTextMargins(0, 1, queryBtn->width(), 1);

    QLabel * transL = new QLabel(tr("Dictionary:"), ui->toolBar);

    menuBtn = new QMenuButton(ui->toolBar);
    menuBtn->setText(tr("Menu"));
    menuBtn->setObjectName("menuButton");
    menuBtn->setFlat(true);
    menuBtn->setIcon(QIcon(":/resources/pics/menu.png"));
    menuBtn->setFocusPolicy(Qt::NoFocus);

    ui->toolBar->addWidget(transL);
    ui->toolBar->addWidget(dictCombo);
    ui->toolBar->addSeparator();

    inputAction = ui->toolBar->addWidget(inputEdit);

    ui->toolBar->addSeparator();
    ui->toolBar->addWidget(menuBtn);


    QMenu *menu = menuBtn->getmenu();

    MiniTranslator *miniTransor = new MiniTranslator(this);

    menu->addAction(QIcon(":/resources/pics/minitrans.png"), tr("Mini transliterator"), miniTransor, SLOT(show()));
    AboutDialog *transDlg = new AboutDialog(this);
    transDlg->setWindowTitle(tr("Transliteration helper"));
    transDlg->setAbout(QUrl("qrc:/docs/aboutTransliteration.html"));
    menu->addAction(QIcon(":/resources/pics/aboutTrans.png"), "Transliteration helper", transDlg, SLOT(show()));

#if !defined(Q_OS_MAC)
    menu->addSeparator();

    genIdxAction = menu->addAction(QIcon(":/resources/pics/index.png"), tr("Generate index file"));
    connect(genIdxAction, SIGNAL(triggered()), this, SLOT(slotGenIdx()));
#endif

    menu->addSeparator();

    QMenu *aboutDictMenu = menu->addMenu(QIcon(":/resources/pics/aboutDict.png"), "Dictionaries");

    AboutAbhidhaana *aboutApp = new AboutAbhidhaana(this);
    menu->addAction(QIcon(":/resources/pics/aboutApp.png"), tr("About Abhidhaana"), aboutApp, SLOT(exec()));



    connect(queryBtn,SIGNAL(clicked()),this,SLOT(slotQuery()));
    connect(inputEdit, SIGNAL(returnPressed()), this, SLOT(slotQuery()));
    connect(inputEdit, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)));
    connect(ui->wordList,SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(slotWordListClicked(QListWidgetItem*)));

    connect(ui->resultText, SIGNAL(anchorClicked(QUrl)), this, SLOT(slotOpenLink(QUrl)));

    //hide dockWidget titlebar;
    QWidget* titleWidget = new QWidget(this);
    ui->dockWidget->setTitleBarWidget(titleWidget);

    ui->wordList->setMinimumWidth(150);
    ui->resultText->setMinimumWidth(300);


    settings = new QSettings("Cjacker", "Abhidhaana");


    transliterator = new Transliterator();

    loadPlugins();

    if(dictionaryList.size() == 0) {
        QMessageBox::information(this,tr("WARNING"),
                                 tr("Can not load any dictionary plugin,\nAbhidhaana will quit."),
                                 QMessageBox::Ok);
        exit(0);
    }

    for(int i = 0; i < dictionaryList.size(); i++) {
        DictionaryInterface *dict = qobject_cast<DictionaryInterface *>(dictionaryList.at(i));
        connect(dictionaryList.at(i), SIGNAL(readyToShow(QString)), this, SLOT(showMeaning(QString)));
        dictCombo->addItem(dict->getDescription().shortname());
        AboutDialog *dictInfoDlg = new AboutDialog(this);
        dictInfoDlg->setWindowTitle("About " + dict->getDescription().name());
        dictInfoDlg->setAbout(dict->getDescription().about());
        aboutDictMenu->addAction(dict->getDescription().icon(),
                                 "About "+ dict->getDescription().shortname(),
                                 dictInfoDlg, SLOT(exec()));
    }

    int cur = settings->value("CurrentDictionary", 0).toInt();
    //you uninstall a plugin, but cur still had the value large than dictionaryList.size,
    //it will crash.
    cur = qMin(cur, dictionaryList.size()-1);

    currentDict = dictionaryList.at(cur);
    dictCombo->setCurrentIndex(cur);

    if(filterAction) {
        ui->toolBar->removeAction(filterAction);
        filterAction = NULL;
    }

    QWidget *wid = qobject_cast<DictionaryInterface *>(currentDict)->getToolbarFilterWidget();
    if(wid) {
        filterAction = ui->toolBar->insertWidget(inputAction, wid);
        connect(currentDict, SIGNAL(filterChanged()), this, SLOT(dictFilterChanged()));
    } else {
        filterAction = NULL;
    }

    //after everything setup, connect the signal.
    //otherwise, it will emit currentIndexChanged signal when setup it.
    connect(dictCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeDictionary(int)));

    setTabOrder(inputEdit, ui->resultText);
    setTabOrder(ui->resultText, ui->wordList);
    setTabOrder(ui->wordList, menuBtn);
    setTabOrder(menuBtn, dictCombo);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::showEvent(QShowEvent *e)
{
    inputEdit->setFocus();
    QMainWindow::showEvent(e);
}

void MainWindow::loadPlugins()
{
    QDir pluginsDir(qApp->applicationDirPath());
#if defined(Q_OS_WIN)
    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
        pluginsDir.cdUp();
/*#elif defined(Q_OS_MAC)
    if (pluginsDir.dirName() == "MacOS") {
        pluginsDir.cdUp();
        pluginsDir.cdUp();
        pluginsDir.cdUp();
    }*/
#endif
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
#if defined(Q_OS_WIN)
        if(fileName.endsWith(".a"))
            continue;
#endif
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            dictionaryList.append(plugin);
        } else {
            QString error = fileName + ":\n" + pluginLoader.errorString();
            QMessageBox::warning(this, "Plugin error", error, QMessageBox::Ok);
        }
    }
}
void MainWindow::slotGenIdx()
{
    QString gencmd = QCoreApplication::applicationDirPath() + "/genmonieridx2";
    QProcess::startDetached(gencmd);
}


void MainWindow::slotChangeDictionary(int i)
{
    currentDict = dictionaryList.at(i);

    ui->wordList->clear();
    inputEdit->setText("");

    if(filterAction) {
        ui->toolBar->removeAction(filterAction);
        filterAction = NULL;
    }

    QWidget *wid = qobject_cast<DictionaryInterface *>(currentDict)->getToolbarFilterWidget();
    if(wid) {
        filterAction = ui->toolBar->insertWidget(inputAction, wid);
        connect(currentDict, SIGNAL(filterChanged()), this, SLOT(dictFilterChanged()));
    } else {
        filterAction = NULL;
    }

    ui->resultText->setText("");

    settings->setValue("CurrentDictionary", i);
}


/*void MainWindow::slotTextChanged(QString text)
{
    if(text.isEmpty() || text.isNull()) {
        ui->wordList->clear();
        return;
    }

    QStringList wordsHash = qobject_cast<DictionaryInterface *>(currentDict)->getCandidateWords(text);

    if(wordsHash.size() == 0)
        return;

    ui->wordList->clear();

    QString fn = qobject_cast<DictionaryInterface *>(currentDict)->getListFontName();

    if(!fn.isNull() && !fn.isEmpty()) {
        ui->wordList->setFont(QFont(fn, 14));
    } else {
        ui->wordList->setFont(QFont("DejaVu Sans", 12));
    }

    for(int i = 0; i < wordsHash.size(); i++) {
        ui->wordList->addItem(wordsHash.at(i));
    }
    //goto the top word.
    ui->wordList->setCurrentRow(0);
    if(ui->wordList->currentItem()->text() == text)
        slotQuery(text);
}*/

void MainWindow::dictFilterChanged()
{
    ui->wordList->clear();
    inputEdit->setText("");
}

void MainWindow::slotTextChanged(QString text)
{
    if(text.isEmpty() || text.isNull()) {
        ui->wordList->clear();
        return;
    }

    QList<QPair<QString, QString> > wordsPairList = qobject_cast<DictionaryInterface *>(currentDict)->getCandidateWords(text);

    if(wordsPairList.size() == 0)
        return;

    ui->wordList->clear();

    QString fn = qobject_cast<DictionaryInterface *>(currentDict)->getListFontName();

    if(!fn.isNull() && !fn.isEmpty()) {
        ui->wordList->setFont(QFont(fn, 14));
    } else {
        ui->wordList->setFont(QFont("DejaVu Sans", 12));
    }

    for(int i = 0; i < wordsPairList.size(); i++) {
        QListWidgetItem *item = new QListWidgetItem(ui->wordList);
        item->setText(wordsPairList.at(i).second);
        item->setData(3, QVariant(wordsPairList.at(i).first));
        ui->wordList->addItem(item);
    }

    //goto the top word.
    ui->wordList->setCurrentRow(0);

    //if matched, show result.
    if(wordsPairList.at(ui->wordList->currentRow()).first == text)
        slotQuery(text);
}


void MainWindow::slotQuery(QString text)
{
    if(text.isEmpty() || text.isNull() || text == "") {
        QString html = QString("<html><body><span style=\"font-size:16pt;\">"
                               "Please input word to query.</body></html>");
        ui->resultText->setText(html);
        return;
    }

    qobject_cast<DictionaryInterface *>(currentDict)->queryWord(text);


    //inputEdit->setText(text);
}


void MainWindow::showMeaning(QString html) {
    if(html.isEmpty() || html.isNull()){
        html = QString("<html><body><span style=\"font-size:16pt;\">"
                               "The word <span style=\"color:#0000ff\">'%1'</span> "
                               "not found</span></body></html>").arg(inputEdit->text());
    }

    ui->resultText->setText(html);
}

void MainWindow::slotQuery()
{
    QString key = inputEdit->text();
    /*QString curWord;
    if(ui->wordList->currentItem())
        curWord= ui->wordList->currentItem()->text();
    if(!curWord.isEmpty() && !curWord.isNull()) {
        key = curWord;
        inputEdit->setText(ui->wordList->currentItem()->data(3).toString());
    }*/
    slotQuery(key);
}


void MainWindow::slotWordListClicked(QListWidgetItem * item)
{
    if(!item)
        return;
    slotQuery(item->text());

    inputEdit->setText(item->data(3).toString());
}



//himadIDiti
void MainWindow::slotOpenLink(QUrl uri)
{
    //printf("url:%s\n", uri.toString().toStdString().c_str());
    if(uri.scheme() == "query") {
        QString key = uri.authority().replace("_", " ");
        slotQuery(key);
        inputEdit->setText(key);
        return;
    } else if(uri.scheme().startsWith("tooltip")) {
            QString protocol = uri.scheme();
            QString key = uri.authority();
            QString tip = qobject_cast<DictionaryInterface *>(currentDict)->getTooltip(protocol, key);
            if(!tip.isNull())
                QToolTip::showText(QCursor::pos(),tip);
            return;
    } else
        QDesktopServices::openUrl(uri);
}

